#pragma once
#include <memory>
#include "Socket.hpp"
#include "epoller.hpp"
static const uint16_t Defaultport = 8888;
class epollServer
{
private:
    shared_ptr<Sock> _listensocK_ptr;
    shared_ptr<epoller> _epoller_ptr;
    uint16_t _port;

public:
    epollServer(uint16_t port = Defaultport) : _listensocK_ptr(new Sock()), _epoller_ptr(new epoller()), _port(port) {}
    void Init()
    {
        _listensocK_ptr->Socket();
        _listensocK_ptr->Bind(_port);
        _listensocK_ptr->Listen();
    }
    void Accepter()
    {
        string clientip;
        uint16_t clientport;
        int sockfd = _listensocK_ptr->Accept(clientip, clientport);
        if (sockfd > 0)
        {
            cout << "get a new link ,clientip:" << clientip.c_str() << ",clientport:" << clientport << endl;
            _epoller_ptr->Epollerupdate(EPOLL_CTL_ADD, sockfd, EPOLLIN);
        }
    }
    void Recever(int fd)
    {
        char buffer[1024];
        ssize_t n = read(fd, buffer, sizeof(buffer) - 1);
        if (n > 0)
        {
            buffer[n] = 0;
            cout << "get a message : " << buffer << endl;

            string str = "server send a message :";
            str += buffer;
            write(fd, str.c_str(), str.size());
        }
        else if (n == 0)
        {
            cout << "client quit" << endl;
            _epoller_ptr->Epollerupdate(EPOLL_CTL_DEL, fd, 0);
            close(fd);
        }
        else
        {
            lg(Warning, "recv error: fd is : %d", fd);
            _epoller_ptr->Epollerupdate(EPOLL_CTL_DEL, fd, 0);
            close(fd);
        }
    }
    void Dispatcher(struct epoll_event reves[], int n) // 时间派发器
    {
        for (int i = 0; i < n; i++)
        {
            int fd = reves[i].data.fd;
            uint32_t revent = reves[i].events;
            if (revent == EPOLLIN)
            {
                if (fd == _listensocK_ptr->Fd())
                {
                    Accepter();
                }
                else
                {
                    Recever(fd);
                }
            }
        }
    }
    void Start()
    {

        int maxevents = 64;
        struct epoll_event reves[maxevents];
        _epoller_ptr->Epollerupdate(EPOLLIN, _listensocK_ptr->Fd(), EPOLL_CTL_ADD);
        while (1)
        {
            int n = _epoller_ptr->EpollerWait(reves, maxevents);
            if (n == 0)
            {
                lg(Info, "time out ...");
            }
            else if (n > 0)
            {
                lg(Debug, "event happened, fd is : %d", reves[0].data.fd);
                Dispatcher(reves, n);
            }
            else
            {
                lg(Error, "epll wait error");
            }
        }
    }
    ~epollServer()
    {
        if (_listensocK_ptr->Fd() >= 0)
            close(_listensocK_ptr->Fd());
    }
};